package chapter05

/**
 * Created with IntelliJ IDEA.
 * ClassName: Test05_Lambda
 * Package: chapter05
 * Description:
 * User: fzykd
 *
 * @Author: LQH
 *          Date: 2023-06-19
 *          Time: 16:11
 */

object Test05_Lambda {
  def main(args: Array[String]): Unit = {
    //匿名函数 lambda表达式
    //这表示一个函数类型 String为参数 Unit作为返回值
    //val stringToUnit: String => Unit = (name:String) => {println(name)}
    val fun = (name: String) => {
      println(name)
    }
    //既然是函数就有返回值 将返回值给fun变量 变量的类型就是函数类型
    fun("匿名函数")

    println("-------------------")

    //实际运用 以函数作为一个参数输入
    def f(func: String => Unit): Unit = {
      func("调来调去")
    }
    //所以调用f的时候 里面也要传一个以String为参数 Unit为返回值类型的函数
    f(fun)
    //解析 1.f调用的时候底层调用了func 以String为参数 Unit为返回值的函数
    //这个函数的参数就是 fun函数 那执行fun得有参数吧 参数就是func()中的参数
    f((name: String) => {
      println(name)
    }) //实际使用 直接传一个匿名函数


    //匿名函数的简化
    //（1）参数的类型可以省略，会根据形参进行自动的推导
    f((name) => {
      println(name)
    })
    //（2）类型省略之后，发现只有一个参数，则圆括号可以省略；其他情况：没有参数和参
    f(name => {
      println(name)
    })
    //数超过 1 的永远不能省略圆括号。
    //（3）匿名函数如果只有一行，则大括号也可以省略
    f(name => println(name))
    //（4）如果参数只出现一次，则参数省略且后面参数可以用_代替
    f(println(_))
    // (5) 如果推断出 当前传入的println是一个函数体 而不是调用语句 可以直接省略下划线
    f(println)


    //实际案列
    //定义一个”二元运算“函数 只操作1和2两个数 但是具体运算通过参数
    //表示一个函数类型 (Int,Int)=>Int 参数是两个Int Int 返回值 也是Int
    //以前是传数值 固定加减乘除 现在固定数值 给加减乘除当参数
    def dualFunctionOneAndTwo(fun: (Int, Int) => Int): Int = {
      fun(1, 2)
    }

    //定义+
    val add = (a: Int, b: Int) => a + b
    //定义-
    val minus = (a: Int, b: Int) => a - b
    println(dualFunctionOneAndTwo(add))
    println(dualFunctionOneAndTwo(minus))

    //匿名函数简化 名称可以省略
    println(dualFunctionOneAndTwo((a: Int, b: Int) => a + b))
    println(dualFunctionOneAndTwo((a: Int, b: Int) => a - b))
    //再简化 参数类型也是定义死了的 也没必要写了
    println(dualFunctionOneAndTwo((a, b) => a + b))
    //再简化 参数只出现一次使用下划线代替
    println(dualFunctionOneAndTwo(_+_))
    println(dualFunctionOneAndTwo(_-_))
    //如果要实现b-a的话
    println(dualFunctionOneAndTwo(-_+_))


  }
}
